package com.seahorse.youliao.controller.base;

import com.seahorse.youliao.common.ResponseEntity;
import com.seahorse.youliao.common.ResponseHandler;
import com.seahorse.youliao.config.WeChatPayConfigs;
import com.seahorse.youliao.constant.PayResultConstants;
import com.seahorse.youliao.entity.wechat.WeChatPayNotifyEntity;
import com.seahorse.youliao.entity.wechat.WeChatResultEntity;
import com.seahorse.youliao.exception.BusinessException;
import com.seahorse.youliao.service.WeChatPayService;
import com.seahorse.youliao.utils.WeChatXmlUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * @description: 微信支付
 * @author: Mr.Song
 * @create: 2020-03-07 16:34
 **/
@Api(value = "WeChatPayController", tags = "支付-微信支付接口")
@Controller
@RequestMapping("/weChatPay")
public class WeChatPayController {

    private static Logger logger = LoggerFactory.getLogger(WeChatPayController.class);

    @Autowired
    private WeChatPayService weChatPayService;

    /**
     * 微信扫码支付下单生成二维码展示
     * @param orderNo 订单号
     * @return
     */
    @ApiOperation(value = "微信扫码支付二维码展示")
    @PostMapping(value = "/createTradeQRCode/{orderNo}")
    public ResponseEntity createTradeQRCode(@PathVariable String orderNo) throws Exception{

        ResponseEntity responseEntity = new ResponseEntity();
        logger.info("微信扫码付 下单 orderNo = " + orderNo);
        //生成下单二维码订单信息
        String base64 = weChatPayService.createTradeQRCode(orderNo);
        responseEntity.setResult(base64);
        return responseEntity;

    }


    /**
     * 微信退款
     * 同一笔支付交易可以多次退款
     * 退款的总额不能超出交易总额
     * @param orderNo 订单号
     * @return
     */
    @ApiOperation(value = "微信退款")
    @PostMapping("/tradeRefund/{orderNo}")
    public ResponseEntity tradeRefund(@PathVariable String orderNo) {

        logger.info("支付宝退款 orderNo = " + orderNo);
        try {
            weChatPayService.tradeRefund(orderNo);
        } catch (Exception e) {
            logger.error(e.toString());
            ResponseEntity.error(e.getMessage());
        }
        return ResponseEntity.ok("成功");
    }


    /**
     * 微信第三方查询扫码支付结果
     * @param orderNo 订单号
     * @return
     */
    @ApiOperation(value = "微信第三方查询扫码支付结果")
    @PostMapping("/tradeQuery/{orderNo}")
    public ResponseEntity tradeQuery(@PathVariable String orderNo) {

        logger.info("查询微信扫码支付结果 orderNo = " + orderNo);
        try {
            weChatPayService.tradeQuery(orderNo);
        } catch (Exception e) {
            logger.error(e.toString());
            ResponseEntity.error(e.getMessage());
        }
        return ResponseEntity.ok("成功");
    }


    /**
     * 微信支付成功异步通知
     * SUCCESS/FAIL
     * SUCCESS表示商户接收通知成功并校验成功
     * @param request
     * @return
     */
    @ResponseHandler(handler = false)
    @ApiOperation(value = "微信支付成功异步通知")
    @GetMapping(value = "callback")
    public WeChatResultEntity callback(HttpServletRequest request) throws Exception{

        logger.info("微信支付成功异步通知  --》 callback");

        //将结果转换为字符
        StringBuilder builder = getResultCallback(request);
        logger.info("webChatPayActionCallback -> 微信成功异步回调，结果：" + builder);

        //处理支付成功异步通知
        return this.wxPayNotifyCallback(builder);
    }


    /**
     * 微信支付-退款 回调通知
     * @param request
     * @return
     */
    @ApiOperation(value = "微信支付-退款 回调通知")
    @GetMapping(value = "/refundCallBack")
    public WeChatResultEntity refundCallBack(HttpServletRequest request) throws Exception{

        logger.info("微信支付-退款  --》 refundCallBack ");

        //将结果转换为字符
        StringBuilder builder = getResultCallback(request);
        logger.info("webChatPayActionCallback -> 微信支付-退款 回调通知，结果：" + builder);

        //微信支付-退款 回调通知
        return weChatPayService.refundCallBack(builder);
    }


    /**
     * 获取返回结果并转换为字段串
     *
     * @param request http
     * @return 返回解析结果
     */
    protected StringBuilder getResultCallback(HttpServletRequest request) {
        StringBuilder builder = new StringBuilder();
        try {
            //验证 HTTP 是否为空
            if (request == null){
                return builder;
            }
            //获取流数据
            InputStream stream = request.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(stream));

            //读取数据
            String line = null;
            while ((line = reader.readLine()) != null) {
                builder.append(line);
            }
            //返回结果
            return builder;
        } catch (Exception ex) {
            logger.error(ex.toString());
            return builder;
        }
    }


    /**
     * 微信支付异步回调通知
     *
     * @param builder
     * @return
     */
    public WeChatResultEntity wxPayNotifyCallback(StringBuilder builder) throws Exception {

        logger.info("XML：" + builder.toString());
        WeChatResultEntity resultEntity = new WeChatResultEntity();
        //订单记录


        //将数据转换为实体
        WeChatPayNotifyEntity entity = WeChatXmlUtil.xmlToBean(WeChatPayNotifyEntity.class, builder.toString());

        //根据outTradeNo 查询订单号

        //验证是否成功 如果失败则直接跳过
        if (PayResultConstants.SUCCESS.equals(entity.getResultCode())) {

            //验证签名
            SortedMap<String, String> data = new TreeMap<>();
            data.put("appid", WeChatPayConfigs.APP_ID);
            data.put("mch_id", WeChatPayConfigs.MCH_ID);
            data.put("nonce_str", entity.getNonceStr());
            data.put("bank_type", entity.getBankType());
            data.put("cash_fee", entity.getCashFee());
            data.put("fee_type", entity.getFeeType());
            data.put("is_subscribe", entity.getIsSubscribe());
            data.put("openid", entity.getOpenId());
            data.put("out_trade_no", entity.getOutTradeNo());
            data.put("trade_type", entity.getTradeType());
            data.put("return_code", entity.getReturnCode());
            data.put("result_code", entity.getResultCode());
            data.put("time_end", entity.getTimeEnd());
            data.put("total_fee", entity.getTotalFee());
            data.put("transaction_id", entity.getTransactionId());
            if (!StringUtils.isEmpty(entity.getCouponFee0())) {
                data.put("coupon_fee_0", entity.getCouponFee0());
            }

            if (!StringUtils.isEmpty(entity.getCouponId0())) {
                data.put("coupon_id_0", entity.getCouponId0());
            }

            if (!StringUtils.isEmpty(entity.getCouponCount())) {
                data.put("coupon_count", entity.getCouponCount());
            }

            if (!StringUtils.isEmpty(entity.getCouponFee())) {
                data.put("coupon_fee", entity.getCouponFee());
            }

            //生成签名信息
            String sign = WeChatXmlUtil.generateSignature(data, WeChatPayConfigs.API_KEY);

            //验证签名
            logger.info("验证签名：" + sign + "，getSign：" + entity.getSign());
            if (!sign.equals(entity.getSign())) {
                logger.info("签名效验失败！");
                throw new BusinessException("签名效验失败！");
            }
            //支付成功  通知

        }else{
            //支付失败

        }
        //更新业务记录支付状态为成功
        logger.info("更新业务记录支付状态为成功！");



        return resultEntity;
    }

}
